package com.xtayfjpk.guava.test.concurrent;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import com.google.common.util.concurrent.Monitor;

public class SafeBox {
	private final Monitor monitor = new Monitor();
	private final Monitor.Guard valuePresent = new Monitor.Guard(monitor) {
		public boolean isSatisfied() {
			return value != null;
		}
	};
	private final Monitor.Guard valueAbsent = new Monitor.Guard(monitor) {
		public boolean isSatisfied() {
			return value == null;
		}
	};
	private Object value;

	public Object get() throws InterruptedException {
		monitor.enterWhen(valuePresent);
		try {
			Object result = value;
			value = null;
			return result;
		} finally {
			monitor.leave();
		}
	}

	public void set(Object newValue) throws InterruptedException {
		monitor.enterWhen(valueAbsent);
		try {
			value = newValue;
		} finally {
			monitor.leave();
		}
	}
	
	public static class SafeBox2 {
		private final ReentrantLock lock = new ReentrantLock();
		private final Condition valuePresent = lock.newCondition();
		private final Condition valueAbsent = lock.newCondition();
		private Object value;

		public Object get() throws InterruptedException {
			lock.lock();
			try {
				while (value == null) {
					valuePresent.await();
				}
				Object result = value;
				value = null;
				valueAbsent.signal();
				return result;
			} finally {
				lock.unlock();
			}
		}

		public void set(Object newValue) throws InterruptedException {
			lock.lock();
			try {
				while (value != null) {
					valueAbsent.await();
				}
				value = newValue;
				valuePresent.signal();
			} finally {
				lock.unlock();
			}
		}
	}
	
	public static void main(String[] args) {
		
	}
	
	
}